/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tree;

/**
 *
 * @author Ej-Dý
 */
/**
 * Vnitrni forma: binarni operator.
 */
public class BinaryTree extends VyrazTree {
    
    @Override
    public Type getType() {
        if ((leftOperand.getType() != Type.STRING &&  leftOperand.getType() != Type.ARRAY) && (rightOperand.getType() == Type.CONV &&  leftOperand.getType() != Type.ARRAY) ) {
            
        }
        else if (leftOperand.getType() == Type.STRING || rightOperand.getType() == Type.STRING) {
                        
            return Type.STRING;
            
        }
        return Type.INTEGER;
    }
    
    @Override
    public void setType(Type t) {
        leftOperand.setType(t);
        rightOperand.setType(t);
    }
    
    public enum Operator {
        
        VETSIROV,
        MENSIROV,
        NEROVNO,
        MENSI,
        VETSI,
        ROVNO,
        PRIRAZENI,
        KRAT,
        DELENO,
        MINUS,
        PLUS
    }
    private Operator operator;
    private VyrazTree leftOperand;
    private VyrazTree rightOperand;
    
    public BinaryTree(Position start, Position end, Operator operator,
            VyrazTree leftOperand, VyrazTree rightOperand) {
        super(start, end);
        this.operator = operator;
        this.leftOperand = leftOperand;
        this.rightOperand = rightOperand;
    }
    
    public Operator getOperator() {
        return operator;
    }
    
    public VyrazTree getLeftOperand() {
        return leftOperand;
    }
    
    public void setLeftOperand(VyrazTree leftOperand) {
        this.leftOperand = leftOperand;
    }
    
    public VyrazTree getRightOperand() {
        return rightOperand;
    }
    
    public void setRightOperand(VyrazTree rightOperand) {
        this.rightOperand = rightOperand;
    }
    
    @Override
    public void accept(TreeVisitor visitor) {
        visitor.visitBinary(this);
    }
    
    @Override
    public void generate(Context ctx) {
        convert();
        leftOperand.generate(ctx);
        Type t1 = leftOperand.getType();
        rightOperand.generate(ctx);
        Type t2 = rightOperand.getType();
        
        boolean string = (t1 == Type.STRING) || (t2 == Type.STRING);
        switch (operator) {
            case PLUS:
                if (string) {
                    ctx.println("sadd");
                    
                } else {
                    ctx.println("iadd");                    
                }
                
                
                
                break;
            case MINUS:
                
                ctx.println("isub");
                
                break;
            case KRAT:
                
                ctx.println("imul");
                
                break;
            case DELENO:
                
                ctx.println("idiv");
                
                break;
            
            case ROVNO:
                
                ctx.println("if ne " + ctx.getAttr("lab"));
                
                break;
            case NEROVNO:
                
                ctx.println("if eq " + ctx.getAttr("lab"));
                
                break;
            case MENSI:
                
                ctx.println("if ge " + ctx.getAttr("lab"));
                
                break;
            case VETSI:
                
                ctx.println("if le " + ctx.getAttr("lab"));
                
                break;
            case MENSIROV:
                
                ctx.println("if gt " + ctx.getAttr("lab"));
                
                break;
            case VETSIROV:
                
                ctx.println("if lt " + ctx.getAttr("lab"));
            
        }
    }
    
    @Override
    public String toString() {
        return String.format("Binary %s: [%s, %s, %s]", super.toString(), leftOperand, operator, rightOperand);
    }
    
    private void convert(){
           if (leftOperand.getType() == Type.STRING || rightOperand.getType() == Type.STRING) {
            
            if (leftOperand.getType() == Type.INTEGER || leftOperand.getType() == Type.ARRAY || leftOperand.getType() == Type.POINTER ) {
                
                leftOperand.setType(Type.CONV);
                
            } 
            else if (rightOperand.getType() == Type.INTEGER || rightOperand.getType() == Type.ARRAY || rightOperand.getType() == Type.POINTER  ) {
                
                rightOperand.setType(Type.CONV);
                
            }
        }
    }
    
}
